
import numpy as np

class Config(object):
    '''
    GPU_COUNT、IMAGES_PER_GPU、NUM_CLASSES
    这三个参数在这里不需要修改，仅用于定义
    '''
    #-------------------------#
    #   GPU数量
    #-------------------------#
    GPU_COUNT       = 1
    #-------------------------#
    #   每个GPU的图片数量
    #-------------------------#
    IMAGES_PER_GPU  = 1
    #-------------------------------------#
    #   分类类别数（包括背景）
    #-------------------------------------#
    NUM_CLASSES     = 1 
    
    '''
    输入到网络中预测的图像大小
    '''
    #------------------------------------------------------------#
    #   调整大小并用零填充以获得大小的方形图像 [max_dim, max_dim].
    #------------------------------------------------------------#
    IMAGE_MAX_DIM   = 1024
    

    '''
    网络构建时的一些参数
    '''
    #-------------------------------------#
    #   特征金字塔的通道数大小
    #-------------------------------------#
    TOP_DOWN_PYRAMID_SIZE       = 256
    #-------------------------------------#
    #   对建议框进行分类的全连接层的大小
    #-------------------------------------#
    FPN_CLASSIF_FC_LAYERS_SIZE  = 1024
    #-------------------------------------#
    #   池化方式
    #-------------------------------------#
    POOL_SIZE       = 7
    MASK_POOL_SIZE  = 14
    MASK_SHAPE      = [28, 28]
    #-------------------------------------#
    #   是否冻结BN层、默认不训练BN层
    #-------------------------------------#
    TRAIN_BN        = False 

    '''
    该部分参数用于计算先验框
    '''
    #---------------------------------#
    #   建议框的先验框的长度（像素）
    #---------------------------------#
    RPN_ANCHOR_SCALES   = [32, 64, 128, 256, 512]
    #---------------------------------#
    #   先验框的变化比率
    #---------------------------------#
    RPN_ANCHOR_RATIOS   = [0.5, 1, 2]
    #---------------------------------#
    #   特征金字塔的步长
    #   对输入进来的特征层压缩
    #   2次、3次、4次、5次、6次
    #---------------------------------#
    BACKBONE_STRIDES    = [4, 8, 16, 32, 64]
    #---------------------------------#
    #   先验框的步长
    #---------------------------------#
    RPN_ANCHOR_STRIDE   = 1
    
    '''
    预测与训练时，建议框、预测框的参数设置
    '''
    #-------------------------------------#
    #   非极大抑制前的建议框的数量
    #-------------------------------------#
    PRE_NMS_LIMIT           = 6000
    #---------------------------------#
    #   建议框的非极大抑制的iou门限
    #---------------------------------#
    RPN_NMS_THRESHOLD       = 0.7
    #-------------------------------------#
    #   非最大抑制后保持的建议框数量
    #   （训练和推理）
    #-------------------------------------#
    POST_NMS_ROIS_TRAINING  = 2000
    POST_NMS_ROIS_INFERENCE = 1000
    #-------------------------------------#
    #   每个图像有多少先验框用于RPN训练
    #-------------------------------------#
    RPN_TRAIN_ANCHORS_PER_IMAGE = 256
    #-------------------------------------#
    #   训练用的建议框数量
    #-------------------------------------#
    TRAIN_ROIS_PER_IMAGE        = 200
    #-------------------------------------#
    #   建议框中正样本的比例
    #-------------------------------------#
    ROI_POSITIVE_RATIO  = 0.33
    #-------------------------------------#
    #   最大正样本数量
    #-------------------------------------#
    MAX_GT_INSTANCES    = 100
    #-------------------------------------#
    #   是否使用Mini Mask，及其高宽
    #-------------------------------------#
    USE_MINI_MASK       = True
    MINI_MASK_SHAPE     = (56, 56)
    
    #-----------------------------------------#
    #   最大检测数量、置信度与非极大抑制门限
    #-----------------------------------------#
    DETECTION_MAX_INSTANCES     = 100
    DETECTION_MIN_CONFIDENCE    = 0.7
    DETECTION_NMS_THRESHOLD     = 0.3
    
    #-----------------------------------------#
    #   标准化比率，用于改变回归结果的数量级
    #-----------------------------------------#
    RPN_BBOX_STD_DEV    = np.array([0.1, 0.1, 0.2, 0.2])
    BBOX_STD_DEV        = np.array([0.1, 0.1, 0.2, 0.2])
    
    #-----------------------------------------#
    #   损失的比重
    #-----------------------------------------#
    LOSS_WEIGHTS = {
        "rpn_class_loss": 1.,
        "rpn_bbox_loss": 1.,
        "mrcnn_class_loss": 1.,
        "mrcnn_bbox_loss": 1.,
        "mrcnn_mask_loss": 1.
    }
    
    def __init__(self):
        #-----------------------------------------#
        #   计算BATCH
        #-----------------------------------------#
        self.BATCH_SIZE = self.IMAGES_PER_GPU * self.GPU_COUNT
        
        self.IMAGE_SHAPE        = np.array([self.IMAGE_MAX_DIM, self.IMAGE_MAX_DIM, 3])
        self.IMAGE_META_SIZE    = 1 + 3 + 3 + 4 + 1 + self.NUM_CLASSES

    def display(self):
        print("\nConfigurations:")
        for a in dir(self):
            if not a.startswith("__") and not callable(getattr(self, a)):
                print("{:30} {}".format(a, getattr(self, a)))
        print("\n")
